﻿#region Includes
using System;
using System.Text;
using System.Drawing;
using OpenTK;
using OpenTK.Graphics.OpenGL;
#endregion

namespace GingerGL.Graphics
{
    //------------------------------------------------------------//
    /// <summary>
    /// Graphic Text Base Class
    /// </summary>
    public abstract class Text : IDisposable
    {
        //--------------------------------------------------------//
        #region Variables
        public const int MaxChars = 256;
        public const int DefaultFontSize = 16;
        #endregion
        //--------------------------------------------------------//
        #region Properties
        /// <summary>
        /// Gets/Set Base Index for Display List
        /// </summary>
        protected int Base { get; private set; }
        /// <summary>
        /// Gets Texture Containing Font
        /// </summary>
        public Texture Font { get; protected set; }
        /// <summary>
        /// Gets Size of Font
        /// </summary>
        public int Size { get; protected set; }
        #endregion
        //--------------------------------------------------------//
        #region Constructors
        /// <summary>
        /// Initializes a new instance of object
        /// </summary>
        public Text(Image img)
        {
            this.Font = Texture.Instance.FromImage(img);
            this.Size = DefaultFontSize;
            this.Base = GL.GenLists(MaxChars);
            this.BuildFont();
        }
        #endregion
        //--------------------------------------------------------//
        #region Methods
        /// <summary>
        /// Draws Text to Screen
        /// </summary>
        /// <param name="position">Position to put text</param>
        /// <param name="message">Message to be Displayed</param>
        /// <param name="charset">Which Character Set to use? (0 or 1)</param>
        protected abstract void Draw(Vector3 position, string message, int charset);
        /// <summary>
        /// Builds Font Display List
        /// </summary>
        private void BuildFont()
        {
            float cx;                                                       // Holds Our X Character Coord
            float cy;
            // Holds Our Y Character Coord
            GL.BindTexture(TextureTarget.Texture2D, this.Font.TextureId);   // Select Our Font Texture
            for (int loop = 0; loop < 256; loop++)                          // Loop Through All 256 Lists
            {
                cx = ((float)(loop % this.Size)) / this.Size;               // X Position Of Current Character
                cy = ((float)(loop / this.Size)) / this.Size;               // Y Position Of Current Character
                GL.NewList(this.Base + loop, ListMode.Compile);             // Start Building A List
                GL.Begin(BeginMode.Quads);                                  // Use A Quad For Each Character
                GL.TexCoord2(cx, 1 - cy);                                   // Texture Coord (Top Left)
                GL.Vertex2(0, 0);                                           // Vertex Coord (Bottom Left)
                GL.TexCoord2(cx + 0.0625f, 1 - cy);                         // Texture Coord (Top Right)
                GL.Vertex2(this.Size, 0);                                   // Vertex Coord (Bottom Right)
                GL.TexCoord2(cx + 0.0625f, 1 - cy - 0.0625f);               // Texture Coord (Bottom Right)
                GL.Vertex2(this.Size, this.Size);                           // Vertex Coord (Top Right)
                GL.TexCoord2(cx, 1 - cy - 0.0625f);                         // Texture Coord (Bottom Left)
                GL.Vertex2(0, this.Size);                                   // Vertex Coord (Top Left)
                GL.End();                                                   // Done Building Our Quad (Character)
                GL.Translate(10, 0, 0);                                      // Move To The Right Of The Character
                GL.EndList();                                               // Done Building The Display List
            }
        }
        /// <summary>
        /// Disposes this object from video memory
        /// </summary>
        public void Dispose() 
        {
            this.Font.Dispose();
            GL.DeleteLists(this.Base, MaxChars);
        }
        /// <summary>
        /// Equals?
        /// </summary>
        public override bool Equals(object obj)
        {
            return base.Equals(obj);
        }
        /// <summary>
        /// Get hashcode
        /// </summary>
        public override int GetHashCode()
        {
            return base.GetHashCode() ^ this.Base.GetHashCode() ^ this.Font.GetHashCode() ^ this.Size.GetHashCode();
        }
        /// <summary>
        /// Text to string
        /// </summary>
        public override string ToString()
        {
            return "Text";
        }
        #endregion
        //--------------------------------------------------------//
    }
    //------------------------------------------------------------//
}
